bitkeeper revision 1.1236.1.114 (42407a31Nf9p7AkNdYSNJUqcXa7-NA)
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Tue, 22 Mar 2005 20:04:01 +0000 (20:04 +0000)
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Tue, 22 Mar 2005 20:04:01 +0000 (20:04 +0000)
Fix XCHG instruction emulation.
Signed-off-by: Keir Fraser <keir@xensource.com>
tools/tests/test_x86_emulator.c
xen/arch/x86/x86_emulate.c

index 4347727488331726f448932a5120f26a81258949..e6df8092bcfeea98426ea0ddf71997c6392d59e3 100644 (file)
@@ -134,9 +134,42 @@ int main(int argc, char **argv)
         goto fail;
     printf("okay\n");
 
+    printf("%-40s", "Testing lock cmpxchgb %%cl,(%%eax)...");
+    instr[0] = 0xf0; instr[1] = 0x0f; instr[2] = 0xb0; instr[3] = 0x08;
+    regs.eflags = 0x200;
+    regs.eip    = (unsigned long)&instr[0];
+    regs.eax    = 0xAABBCC77UL;
+    regs.ecx    = 0xFF;
+    cr2         = (unsigned long)&res;
+    rc = x86_emulate_memop(&regs, cr2, &emulops, 4);    
+    if ( (rc != 0) || 
+         (res != 0x923456AA) || 
+         ((regs.eflags&0x240) != 0x200) ||
+         (regs.eax != 0xAABBCCAA) ||
+         (regs.ecx != 0xFF) ||
+         (regs.eip != (unsigned long)&instr[4]) )
+        goto fail;
+    printf("okay\n");
+
+    printf("%-40s", "Testing xchgl %%ecx,(%%eax)...");
+    instr[0] = 0x87; instr[1] = 0x08;
+    regs.eflags = 0x200;
+    regs.eip    = (unsigned long)&instr[0];
+    regs.ecx    = 0x12345678;
+    cr2         = (unsigned long)&res;
+    rc = x86_emulate_memop(&regs, cr2, &emulops, 4);    
+    if ( (rc != 0) || 
+         (res != 0x12345678) || 
+         (regs.eflags != 0x200) ||
+         (regs.ecx != 0x923456AA) ||
+         (regs.eip != (unsigned long)&instr[2]) )
+        goto fail;
+    printf("okay\n");
+
     printf("%-40s", "Testing lock cmpxchgl %%ecx,(%%eax)...");
     instr[0] = 0xf0; instr[1] = 0x0f; instr[2] = 0xb1; instr[3] = 0x08;
     regs.eflags = 0x200;
+    res         = 0x923456AA;
     regs.eip    = (unsigned long)&instr[0];
     regs.eax    = 0x923456AAUL;
     regs.ecx    = 0xDDEEFF00L;
@@ -186,7 +219,7 @@ int main(int argc, char **argv)
         goto fail;
     printf("okay\n");
 
-    printf("%-40s", "Testing cmpxchg (%edi) [succeeding]...");
+    printf("%-40s", "Testing cmpxchg8b (%edi) [succeeding]...");
     instr[0] = 0x0f; instr[1] = 0xc7; instr[2] = 0x0f;
     regs.eflags = 0x200;
     regs.eax    = cmpxchg8b_res[0];
@@ -205,7 +238,7 @@ int main(int argc, char **argv)
         goto fail;
     printf("okay\n");
 
-    printf("%-40s", "Testing cmpxchg (%edi) [failing]...");
+    printf("%-40s", "Testing cmpxchg8b (%edi) [failing]...");
     instr[0] = 0x0f; instr[1] = 0xc7; instr[2] = 0x0f;
     regs.eip    = (unsigned long)&instr[0];
     regs.edi    = (unsigned long)cmpxchg8b_res;
index 0ee4bfa62dc6b3d613e90311d507cf1637908ce1..80bac2dca6e8a766ba9e78149507be9511df7248 100644 (file)
@@ -672,6 +672,14 @@ x86_emulate_memop(
         dst.val ^= src.val;
         src.val ^= dst.val;
         lock_prefix = 1;
+        /* Write back the source (temporary register location). */
+        switch ( dst.bytes )
+        {
+        case 1: *(u8  *)src.ptr = (u8)src.val; break;
+        case 2: *(u16 *)src.ptr = (u16)src.val; break;
+        case 4: *src.ptr = (u32)src.val; break; /* 64b mode: zero-extend */
+        case 8: *src.ptr = src.val; break;
+        }
         break;
     case 0xa0 ... 0xa1: /* mov */
         dst.ptr = (unsigned long *)&_regs.eax;